<?php
namespace Jd;

use CookieAuth\BaseLogin;
use Cache\Redis as Cache;
use QL\QueryList;
use JonnyW\PhantomJs\Client;
use JonnyW\PhantomJs\DependencyInjection\ServiceContainer;
use Exceptions\LoginException;

class JdLogin extends BaseLogin
{

    protected $home_url = 'https://passport.jd.com/new/login.aspx';
    protected $login_url = 'https://passport.jd.com/uc/loginService';
    protected $captcha_url = 'https://authcode.jd.com/verify/image';
    protected $auth_code_show_url = 'https://passport.jd.com/uc/showAuthCode';
    protected $order_list_url = 'https://order.jd.com/center/list.action';
    protected $oder_detail_url = '';

    protected $session_id_url = 'https://payrisk.jd.com/fcf.html?r=%7Bfingerprint%3A36e1912f84dc996c637c3751602a37f7%2C%27userAgent%27%3A%27e3734238dc68f3a4b26af89692589815%27%2C%27origin%27%3A%27pc%27%2C%27language%27%3A%27zh-CN%27%2C%27os%27%3A%27windows%27%2C%27osVersion%27%3A%27NT%27%2C%27browser%27%3A%27applewebkit_chrome%27%2C%27browserVersion%27%3A%27537.36%27%2C%27colorDepth%27%3A%2724%27%2C%27screenResolution%27%3A%271080x1920%27%2C%27timezoneOffset%27%3A%27-8%27%2C%27sessionStorage%27%3Atrue%2C%27localStorage%27%3Atrue%2C%27indexedDb%27%3Atrue%2C%27addBehavior%27%3Afalse%2C%27openDatabase%27%3Atrue%2C%27cpu%27%3A%27unknown%27%2C%27platform%27%3A%27Win32%27%2C%27track%27%3A%27unknown%27%2C%27plugins%27%3A%277b84246c4aa604c4272e499b459df11d%27%2C%27canvas%27%3A%276857ceaafec0a90b36451924500a8512%27%2C%27webglFp%27%3A%2738a907e819bdcf3d69f92d42296cc7bd%27%7D&t=P4VRVEB6NDFBBFQ6ONB3VURB26IIBOEWNKRUI2KPFSW4YOFMZ4QB2LGTCKX76XDRSCVPQOWC634DC&pin=&oid=&h=s&fp=36e1912f84dc996c637c3751602a37f7&o=passport.jd.com/new/login.aspx&fc=VAONAZWMS22FNJZVJ37PR6G7UK5AW3GI3VTGQAIE37JLYWK4EHEEQDRS2T3SD36BGAQK5T2D2B74XBKFAWT5YA5SOY';

    protected $cookie_enable = true;
    protected $cookie_file = 'jd_cookie.txt';
    protected $cookie_str = '';

    protected $cache_ttl = 600;

    protected $login_info = [];

    protected $http_headers = [];

    /**
     * init parameters
     *
     * @var
     */
    protected $init_params;

    /**
     * initRequest
     *
     * @return array|null
     */
    protected function initRequest($renew = false)
    {
        $key = $this->cache_key.'_init_params';
        if($renew || !($data = Cache::get($key))){
            $url = $this->home_url;

            $phantomjs_bin = ROOT_PATH.'bin'.DIRECTORY_SEPARATOR.'phantomjs.exe';

            $proc_dir = ROOT_PATH.'phantomjs'.DIRECTORY_SEPARATOR.'php_phantomjs';

            $serviceContainer = ServiceContainer::getInstance();

            $procedureLoader = $serviceContainer->get('procedure_loader_factory')->createProcedureLoader($proc_dir);

            $client = Client::getInstance();

            $client->getEngine()->setPath($phantomjs_bin);

            $client->setProcedure('jd_login');

            $client->getProcedureLoader()->addLoader($procedureLoader);

            $request  = $client->getMessageFactory()->createRequest($url, 'GET');

            $request->setHeaders($this->getHeaders());

            $response = $client->getMessageFactory()->createResponse();

            if($data = $client->send($request, $response)->content){
                Cache::set($key, serialize($data), $this->cache_ttl);
            }
        }

        return $this->init_params = is_string($data) ? unserialize($data) : $data;

        // $rules = [
        //     'uuid' => ['#uuid','value'],
        //     'eid' => ['#eid','value'],
        //     'sessionId' => ['#sessionId','value'],
        //     'token' => ['#token','value'],
        //     'loginType' => ['#loginType','value'],
        //     'pubKey' => ['#pubKey','value'],
        //     'formlogin' => ['#formlogin > input[type="hidden"]:nth-child(7)','value'],
        //     'loginname' => ['#loginname','value'],
        //     'nloginpwd' => ['#nloginpwd','value'],
        //     'autoLogin' => ['#autoLogin','value'],
        //     'authcode' => ['#authcode','value'],
        // ];
        // $range = '#formlogin';



        // if($html = $this->get($url)){
        //     $data = QueryList::Query($html, $rules, $range);
        //     print_r($data);
        //     return $this->init_data = $data->data;
        // }

    }

    /**
     * login
     *
     * @param string $uname
     * @param string $upass
     * @return boolean
     */
    public function login($uname, $upass)
    {
        if(!$uname || !$upass){
            throw new LoginException(__CLASS__.' required username and password');
        }
        $this->login_info['uname'] = $uname;
        $this->login_info['upass'] = $upass;
        $this->cache_key = $this->getCacheKey($uname.$upass);

        if($init_params = $this->initRequest()){
            $this->cookie_str = $cookie_str = implode('; ', $init_params['cookie_str']);
            $inputs = $init_params['inputs'];
            $pubkey = $inputs['pubKey'];
            unset($inputs['pubKey']);
            $url_params = $this->getRandomUrlParams([
                'uuid' => $inputs['uuid'],
                'ReturnUrl' => 'https://www.jd.com/',
            ]);

            if($this->needCaptcha()){
                $img_file = $this->getCaptcha();
                var_dump($img_file);exit;
            }

            $auth_code = '';
            $form_data = [
                'loginType' => 'f',
                'loginname' => $this->login_info['uname'],
                'loginpwd' => $this->login_info['upass'],
                // 'nloginpwd' => '',
                'chkRememberMe' => 'on',
                'authcode' => $auth_code,
            ] + $inputs;
            //could encryption
            if($e_pass = $this->encryptByPubKey($this->login_info['upass'], $pubkey)){
                $form_data['nloginpwd'] = $e_pass;
                unset($form_data['loginpwd']);
            }
            // var_dump($form_data);exit;
            //$this->prepareHttpHeaders('cookie', $cookie_str);
            $url = $this->buildUrl($this->login_url, $url_params);
            $http_headers = [
                'Cookie: '.$cookie_str,
                'Content-Type: application/x-www-form-urlencoded; charset=UTF-8',
            ];
            $curl_option[CURLOPT_HTTPHEADER] = $this->getHeaders($http_headers);
            if($data = $this->post($url, http_build_query($form_data), $curl_option)){
                var_dump($data);
                $this->test();
            }
        }

            // login_data = {
            //     '_t': token,
            //     'authcode': auth_code,
            //     'chkRememberMe': 'on',
            //     'loginType': 'f',
            //     'uuid': self.uuid,
            //     'eid': self.eid,
            //     'fp': self.fp,
            //     'nloginpwd': self.usr_pwd,
            //     'loginname': self.usr_name,
            //     'loginpwd': self.usr_pwd,

            // }

// uuid:3ee0d180-0376-4ae8-99cc-566c5e6317dc
// eid:VAONAZWMS22FNJZVJ37PR6G7UK5AW3GI3VTGQAIE37JLYWK4EHEEQDRS2T3SD36BGAQK5T2D2B74XBKFAWT5YA5SOY
// fp:36e1912f84dc996c637c3751602a37f7
// _t:_ntEoqHq
// loginType:f
// loginname:15921512039
// nloginpwd:eJrImDp564NWNgXMMVHhn7PwsOo/hlZBBPo6RNSVz5OcpaOG1PF6yBbC3bPs5Vtm7OEN+EDz68FfrC7/Sbt+EGibesL4fYUonzuDwqX+84UrcjopIh6oqy6JUrAmJvwEolvTJbfuUOLppbpoaGuDns+kO3e2YOEBOcnkIvrxFBA=
// chkRememberMe:on
// authcode:

#formlogin
#uuid
#eid
#sessionId
#token
#loginType
#pubKey
#formlogin > input[type="hidden"]:nth-child(7)

#loginname
#nloginpwd  pass
#autoLogin
#authcode

// uuid:a7de7e96-3764-4e64-bca6-f40c8acb1df6
// eid:VAONAZWMS22FNJZVJ37PR6G7UK5AW3GI3VTGQAIE37JLYWK4EHEEQDRS2T3SD36BGAQK5T2D2B74XBKFAWT5YA5SOY
// fp:36e1912f84dc996c637c3751602a37f7
// _t:_ntpAUtr
// loginType:c
// loginname:15921512039
// nloginpwd:JpiBEAJAMnR8eIcxH5x67o/4f8WXzJ99Nh/2ldpbU/bS9nZqAkKvi2/P/oHdzhryLXnZMyUFsJ+WfdrkYUlb9gs2XlpO9G1iCCMQYUG703/ii9yYnDPeIdvAdWouAgZJYG8CuVVq3AH+QLMGtyuvvC3SdtyEV3tx3IClZ5i7hlQ=
// chkRememberMe:on
// authcode:



// uuid:3093b155-2a23-444e-97a3-1713c8ddaa03
// ReturnUrl:https://www.jd.com/
// r:0.6319890922759053
// version:2015

// uuid:3093b155-2a23-444e-97a3-1713c8ddaa03
// eid:ATNFPRW7FZIDSCOW5CVRUOIWLJ6UMGMOYNPQ5IBHYBNCAKIFMS2VZGMB7MW5W2SIEWH5JZKPC7RCMWPIW5UI6VWGFE
// fp:48426fdb498a6a195b3b0d2e0776dd13
// _t:_nthCJRf
// loginType:f
// loginname:15921512039
// nloginpwd:HnegEiFwr6JkhpH1r/wiCilC6AQx6CMBRmsobGllOIAFfu6gEjnLzH/x7fBy6xKernHrXPQRGlqAgaZmD0O2Vg3YHWYYmOc4/Kkt/vScMUGmtwN4ApU5N+RvAVsRBTqOWfUCuR9lG4eXMk3JNa/ZY/qvxDcgU+DqSkKZQjNVTWM=
// chkRememberMe:on
// authcode:

    }

    public function test()
    {
        $url = 'https://order.jd.com/center/list.action';
        $data = $this->get($url);
        var_dump($data);
    }

    /**
     * getAuthedSession
     *
     * @return array
     */
    protected function getAuthedSession()
    {

    }

    /**
     * encryptByPubKey
     *
     * @param  string $str
     * @param  string $pubkey
     * @return string|false
     */
    protected function encryptByPubKey($str, $pubkey)
    {
        if(!$str ||!$pubkey){
            return false;
        }
        $encrypt = '';
        return openssl_public_encrypt($str, $encrypt, $this->buildValidPubkey($pubkey)) ? base64_encode($encrypt) : '';
    }

    /**
     * buildValidPubkey
     *
     * @param  string $key
     * @return string|false
     */
    protected function buildValidPubkey($key)
    {
        if(!$key){
            return false;
        }
        if(stripos($key, '-----BEGIN PUBLIC KEY-----') !== false){
            return $key;
        }
        $pubkey = <<<'KEY'
-----BEGIN PUBLIC KEY-----
%s
-----END PUBLIC KEY-----
KEY;
        return sprintf($pubkey, $key);
    }

    /**
     * getRandomUrlParams
     *
     * @return array
     */
    protected function getRandomUrlParams(array $params = [])
    {
        return [
            'r' => '0.'.mt_rand(1319890922759053, 9319890922759053),
            'version' => '2015',
        ] + $params;
    }

    /**
     * needCaptcha
     *
     * @return boolean
     */
    protected function needCaptcha()
    {
        $url = $this->buildUrl($this->auth_code_show_url, $this->getRandomUrlParams());
        $data = http_build_query(['loginName' => $this->login_info['uname']]);
        $option[CURLOPT_HTTPHEADER] =  [
            'Origin: https://passport.jd.com',
            'X-Requested-With: XMLHttpRequest',
            'Content-Type: application/x-www-form-urlencoded; charset=UTF-8',
            'Referer: https://passport.jd.com/uc/login',
            'Accept-Language: zh-CN,zh;q=0.8',
        ];
        if(($data = $this->post($url, $data, $option)) !== false){
            return false;
        }
    }

    /**
     * getCaptcha
     *
     * @return resource|
     */
    protected function getCaptcha()
    {
        $url = $this->buildUrl($this->captcha_url, $this->getRandomUrlParams());
        $data = http_build_query(['loginName' => $this->login_info['uname']]);
        if(($data = $this->post($url, $data)) !== false){
            $img_file = mt_rand(1000,9999).'.png';
            file_put_contents($img_file, $data);
            return $img_file;
        }
        return false;
    }

    /**
     * @param array $config
     * @return array
     */
    public function getCurlConfig(array $config = [])
    {
        $config = array_replace([
            CURLOPT_ENCODING => 'gzip, deflate, sdch, br',
        ], $config);
        return parent::getCurlConfig($config);
    }

    /**
     * description
     *
     * @return array
     */
    protected function prepareHttpHeaders($key = null, $val = null)
    {
        if($key && $key & is_string($key) && is_string($val)){
            return $this->http_headers[] = $key.': '.$val;
        }
        return [];
    }
    /**
     * getHeaders
     *
     * @param  array  $header
     * @return array
     */
    public function getHeaders(array $header = [])
    {
        $data = [
            'Accept-Language:zh-CN,zh;q=0.8',
            'Cache-Control:no-cache',
            'Connection:keep-alive',
            'Pragma:no-cache',
            'DNT:1',
            'Referer:https://www.jd.com/',
            'Upgrade-Insecure-Requests:1',
            'User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2873.0 Safari/537.36',
        ];
        return array_merge($data, $header);
    }

}
